﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Celeriq.Graphing.Core;
using System.ServiceModel;
using System.IO;
using Celeriq.ManagementStudio.UserControls;
using Celeriq.ManagementStudio.EventArguments;
using Celeriq.Common;
using Celeriq.ManagementStudio.Objects;

namespace Celeriq.ManagementStudio
{
	public partial class MainForm : Form
	{
		#region Class Members

		private bool _isConnected = false;
		private WaitForm _progress = null;
		private string _serverName = null;
		private List<RemotingObjectCache> _activeRepositoryList = new List<RemotingObjectCache>();
		private List<RemotingObjectCache> _currentRepositoryList = new List<RemotingObjectCache>();
		private UserCredentials _credentials = null;
		private string _publicKey = string.Empty;
		private ApplicationUserSetting _userSettings = new ApplicationUserSetting();

		#endregion

		#region Constructors

		public MainForm()
		{
			InitializeComponent();

			this.Size = new System.Drawing.Size((int) (Screen.PrimaryScreen.WorkingArea.Width*0.8), (int) (Screen.PrimaryScreen.WorkingArea.Height*0.8));

			this.UpdateStatus();
			EnableMenus();

			_userSettings.Load();
			if (_userSettings.WindowSize.Width != 0)
				this.Size = _userSettings.WindowSize;
			this.WindowState = _userSettings.WindowState;
			this.Location = _userSettings.WindowLocation;

			tvwItem.AfterSelect += new TreeViewEventHandler(tvwItem_AfterSelect);
			tvwItem.KeyDown += new KeyEventHandler(tvwItem_KeyDown);
			this.KeyDown += new KeyEventHandler(MainForm_KeyDown);
			this.Move += MainForm_Move;
			this.ResizeEnd += MainForm_ResizeEnd;
			this.FormClosing += MainForm_FormClosing;

			var timer = new Timer();
			timer.Tick += new EventHandler(timer_Tick);
			timer.Interval = 500;
			timer.Start();
		}

		private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
		{
			_userSettings.Save();
		}

		private void MainForm_ResizeEnd(object sender, EventArgs e)
		{
			ResetWindowState();
		}

		private void MainForm_Move(object sender, EventArgs e)
		{
			ResetWindowState();
		}

		private TreeNode GetRepositoryNode(RemotingObjectCache repository)
		{
			var list = this.AllNodes().Where(x => x.Tag is RemotingObjectCache);
			return list.FirstOrDefault(x => ((RemotingObjectCache)x.Tag).Repository.ID == repository.Repository.ID);
		}

		private TreeNode SelectedRepositoryNode
		{
			get
			{
				var node = tvwItem.SelectedNode;
				if (node == null) return null;

				var cache = node.Tag as RemotingObjectCache;
				if (cache != null)
				{
					return node;
				}
				else if (cache == null && node.Parent != null)
				{
					cache = node.Parent.Tag as RemotingObjectCache;
					if (cache != null)
						return node.Parent;
				}
				return null;
			}
		}

		private void tvwItem_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Delete)
			{
				if (this.SelectedRepositoryNode != null)
				{
					if (MessageBox.Show("Do you wish to delete this repository and all associated data?", "Delete?", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.Yes)
					{
						DeleteRepository(this.ActiveRepository);
					}
				}
			}
			else if (e.KeyCode == Keys.C && e.Control)
			{
				//Copy
				this.CopyRepository();
			}
			else if (e.KeyCode == Keys.V && e.Control)
			{
				//Paste
				this.PasteRepository();
			}
		}

		private List<TreeNode> AllNodes()
		{
			var retval = new List<TreeNode>();
			foreach (TreeNode n in tvwItem.Nodes)
			{
				retval.Add(n);
				retval.AddRange(GetNodes(n));
			}
			return retval;
		}

		private List<TreeNode> GetNodes(TreeNode node)
		{
			var retval = new List<TreeNode>();
			foreach (TreeNode subnode in node.Nodes)
			{
				retval.Add(subnode);
				retval.AddRange(GetNodes(subnode));
			}
			return retval;
		}


		private void MainForm_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.F5)
			{
				this.RefreshFromServer();
			}
		}

		private void timer_Tick(object sender, EventArgs e)
		{
			var timer = sender as Timer;
			timer.Stop();
			this.OpenConnection();
		}

		#endregion

		#region Methods

		private bool ServerConnect(string serverName)
		{
			if (_isConnected) return false;

			try
			{
				this.UpdateStatus("Connecting...");
				_serverName = serverName;
				if (this.RefreshFromServer())
				{
					_isConnected = true;
					this.UpdateStatus();
					this.UpdateStatus("Connected");
					lblServer.Text = "Server: " + serverName.ToUpper();
					return true;
				}
				else
				{
					return false;
				}
			}
			catch (Exception ex)
			{
				_isConnected = false;
				_serverName = string.Empty;
				this.UpdateStatus("Connection Failed!");
				return false;
			}
		}

		private void ServerDisconnect()
		{
			_isConnected = false;
			_serverName = null;
			tvwItem.Nodes.Clear();
			pnlContent.Controls.Clear();
			lblServer.Text = string.Empty;
			_credentials = null;
			_publicKey = string.Empty;
			this.UpdateStatus("Disconnected");
		}

		private TreeNode ServerTreeNode
		{
			get
			{
				if (tvwItem.Nodes.Count > 0 && tvwItem.Nodes[0].Nodes.Count > 0)
					return tvwItem.Nodes[0].Nodes[0];
				return null;
			}
		}

		private bool RefreshFromServer()
		{
			if (string.IsNullOrEmpty(_serverName)) return false;
			try
			{
				pnlContent.Controls.Clear();
				_activeRepositoryList.Clear();
				this.UpdateStatus("Loading...");

				var selText = string.Empty;
				if (this.SelectedRepositoryNode != null)
					selText = this.SelectedRepositoryNode.Text;

				//Save for later setting
				//var active = this.ActiveRepository;
				var isOnRpositoryList = (tvwItem.SelectedNode != null && tvwItem.SelectedNode.Text == "Repositories");
				tvwItem.Nodes.Clear();
				var list = Celeriq.ManagementStudio.Objects.ConnectionCache.GetRepositoryPropertyList(_serverName, _credentials).OrderBy(x => x.Repository.Name);
				var root = tvwItem.Nodes.Add(_serverName);
				var repositoryListNode = root.Nodes.Add("Repositories");
				repositoryListNode.Tag = "REPOSITORYLIST";
				if (isOnRpositoryList)
					tvwItem.SelectedNode = repositoryListNode;

				_currentRepositoryList.Clear();
				_currentRepositoryList.AddRange(list);
				foreach (var item in list)
				{
					this.AddTreeNode(item);
				}

				root.Expand();
				repositoryListNode.Expand();

				if (!string.IsNullOrEmpty(selText))
				{
					var active = repositoryListNode.Nodes.Cast<TreeNode>().FirstOrDefault(x => x.Text == selText);
					this.tvwItem.SelectedNode = active;
				}

				this.UpdateStatus();
				this.EnableMenus();
				return true;
			}
			catch (Exception ex)
			{
				_isConnected = false;
				_serverName = string.Empty;
				this.UpdateStatus("Connection Failed!");
				return false;
			}
			finally
			{
				this.EnableMenus();
			}
		}

		private void AddTreeNode(RemotingObjectCache item)
		{
			try
			{
				var newNode = new TreeNode();
				newNode.Text = item.Repository.Name;
				newNode.Tag = item;
				newNode.ImageIndex = (item.IsLoaded ? 0 : 1);
				newNode.SelectedImageIndex = newNode.ImageIndex;
				ServerTreeNode.Nodes.Add(newNode);

				if (item.Repository != null)
				{
					foreach (var loop in item.Repository.DimensionList)
					{
						var newSubItem = new TreeNode(loop.Name);
						newSubItem.ImageIndex = 3;
						newSubItem.SelectedImageIndex = newSubItem.ImageIndex;
						newNode.Nodes.Add(newSubItem);
					}

					foreach (var loop in item.Repository.FieldList)
					{
						var newSubItem = new TreeNode(loop.Name);
						newSubItem.ImageIndex = 2;
						newSubItem.SelectedImageIndex = newSubItem.ImageIndex;
						newNode.Nodes.Add(newSubItem);
					}
				}
			}
			catch (Exception ex)
			{
				throw;
			}
		}

		private void UpdateStatus()
		{
			UpdateStatus(string.Empty);
		}

		private void UpdateStatus(string text)
		{
			if (string.IsNullOrEmpty(text))
				text = "Ready!";
			lblStatus.Text = text;
		}

		private void EnableMenus()
		{
			menuFileConnect.Enabled = !_isConnected;
			menuFileDisconnect.Enabled = _isConnected;

			cmdNew.Enabled = _isConnected;
			cmdStart.Enabled = (_activeRepositoryList.Count > 0);
			cmdStop.Enabled = (_activeRepositoryList.Count > 0);
			cmdCode.Enabled = (_activeRepositoryList.Count == 1);
			cmdRefresh.Enabled = _isConnected;

			menuSep1.Visible = _isConnected && (_currentRepositoryList.Count > 0);
			menuMainBackup.Visible = _isConnected && (_currentRepositoryList.Count > 0);
			menuMainRestore.Visible = _isConnected && (_currentRepositoryList.Count > 0);
			menuMainServerProp.Enabled = _isConnected;
		}

		private void ResetWindowState()
		{
			if (this.WindowState == FormWindowState.Normal)
				_userSettings.WindowSize = this.Size;
			if (this.WindowState != FormWindowState.Minimized)
				_userSettings.WindowState = this.WindowState;
			if (this.WindowState == FormWindowState.Normal)
				_userSettings.WindowLocation = this.Location;
		}

		#endregion

		#region Properties

		private bool IsActiveRunning
		{
			get { return _activeRepositoryList.All(x => x.IsRunning); }
		}

		public RemotingObjectCache ActiveRepository
		{
			get
			{
				if (this.SelectedRepositoryNode == null) return null;
				return this.SelectedRepositoryNode.Tag as RemotingObjectCache;
			}
		}

		#endregion

		#region Repository Event Handelers

		private delegate void UpdateUICallback(object sender, RepositoryEventArgs e);

		private delegate void ErrorCallback(object sender, RepositoryErrorEventArgs e);

		private void RepositoryStartedHandler(object sender, RepositoryEventArgs e)
		{
			if (this.InvokeRequired)
			{
				var d = new UpdateUICallback(RepositoryStartedHandler);
				this.Invoke(d, new object[] {sender, e});
			}
			else
			{
				var index = _currentRepositoryList.IndexOf(_currentRepositoryList.First(x => x.Repository.ID == e.Repository.Repository.ID));
				_currentRepositoryList[index] = e.Repository;
				index = _activeRepositoryList.IndexOf(_activeRepositoryList.First(x => x.Repository.ID == e.Repository.Repository.ID));
				_activeRepositoryList[index] = e.Repository;

				var n = GetRepositoryNode(e.Repository);
				if (n == null) return;
				n.ImageIndex = (e.Repository.IsRunning ? 0 : 1);
				n.SelectedImageIndex = n.ImageIndex;
				EnableUI();
				this.UpdateStatus();
			}
		}

		private void RepositoryStoppedHandler(object sender, RepositoryEventArgs e)
		{
			if (this.InvokeRequired)
			{
				var d = new UpdateUICallback(RepositoryStoppedHandler);
				this.Invoke(d, new object[] {sender, e});
			}
			else
			{
				var index = _currentRepositoryList.IndexOf(_currentRepositoryList.First(x => x.Repository.ID == e.Repository.Repository.ID));
				_currentRepositoryList[index] = e.Repository;
				index = _activeRepositoryList.IndexOf(_activeRepositoryList.First(x => x.Repository.ID == e.Repository.Repository.ID));
				_activeRepositoryList[index] = e.Repository;

				var n = GetRepositoryNode(e.Repository);
				if (n == null) return;
				n.ImageIndex = (e.Repository.IsRunning ? 0 : 1);
				n.SelectedImageIndex = n.ImageIndex;
				EnableUI();
				this.UpdateStatus();
			}
		}

		private void RepositoryErrorHandler(object sender, RepositoryErrorEventArgs e)
		{
			if (this.InvokeRequired)
			{
				var d = new ErrorCallback(RepositoryErrorHandler);
				this.Invoke(d, new object[] {sender, e});
			}
			else
			{
				Celeriq.Utilities.Logger.LogError(e.Exception);
				EnableUI();
				this.UpdateStatus();
				MessageBox.Show("There was an error connecting to the server.", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void DisableUI()
		{
			_progress = new WaitForm();
			this.MainMenu.Enabled = false;
			this.MainToolbar.Enabled = false;
			this.tvwItem.Enabled = false;
			this.pnlContent.Enabled = false;
			_progress.Show();
			Application.DoEvents();
		}

		private void EnableUI()
		{
			if (_progress != null)
				_progress.Close();
			this.MainMenu.Enabled = true;
			this.MainToolbar.Enabled = true;
			this.tvwItem.Enabled = true;
			this.pnlContent.Enabled = true;
		}

		private void OpenConnection()
		{
			var F = new ServerConnectionForm();
			if (F.ShowDialog() == System.Windows.Forms.DialogResult.OK)
			{
				_credentials = F.Credentials;
				_publicKey = F.PublicKey;
				this.ServerConnect(F.ServerName);
				EnableMenus();
			}
		}

		#endregion

		#region Menu Event Handlers

		private void menuHelpAbout_Click(object sender, EventArgs e)
		{
			var F = new SplashForm();
			F.ShowDialog();
			System.Windows.Forms.Application.DoEvents();
		}

		private void menuFileConnect_Click(object sender, EventArgs e)
		{
			OpenConnection();
		}

		private void menuFileDisconnect_Click(object sender, EventArgs e)
		{
			this.ServerDisconnect();
			EnableMenus();
		}

		private void cmdNew_Click(object sender, EventArgs e)
		{
			try
			{
				var item = new RemotingObjectCache();
				item.Repository = new Common.RepositoryDefinition(){ Name="[New Repository]"};
				item.Repository.FieldList.Add(new Common.FieldDefinition() {DataType = Common.RepositoryDefinition.DataTypeConstants.Int, Name = "ID", IsPrimaryKey = true});
				this.AddTreeNode(item);
				ShowDesignWindow(item);
			}
			catch (Exception ex)
			{
				throw;
			}
		}

		private void cmdLoadSchema_Click(object sender, EventArgs e)
		{
			try
			{
				var dialog = new OpenFileDialog();
				dialog.Title = "Load Schema";
				dialog.FileName = "*.celeriq";
				dialog.Filter = "Schema Files (*.celeriq)|*.celeriq";
				dialog.FilterIndex = 0;
				if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
				{
					var item = new RemotingObjectCache();
					item.Repository = Common.RepositoryDefinition.FromDisk(dialog.FileName);
					this.AddTreeNode(item);

					using (var factory = SystemCoreInteractDomain.GetFactory(_serverName))
					{
						var server = factory.CreateChannel();
						if (server.GetRepositoryPropertyList(_credentials).Count(x => x.Repository.ID == item.Repository.ID) > 0)
						{
							MessageBox.Show("The repository already exists.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
							return;
						}
						server.SaveRepository(item.Repository, _credentials);
					}
					var n = GetRepositoryNode(item);
					n.Text = item.Repository.Name;

					RefreshFromServer();
					EnableUI();
					this.UpdateStatus();

				}
			}
			catch (Exception ex)
			{
				MessageBox.Show("An error occurred!\r\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void cmdCreateFromTemplate_Click(object sender, EventArgs e)
		{
			try
			{
				var dialog = new OpenFileDialog();
				dialog.Title = "Load Template";
				dialog.FileName = "*.celeriq";
				dialog.Filter = "Schema Files (*.celeriq)|*.celeriq";
				dialog.FilterIndex = 0;
				if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
				{
					var item = new RemotingObjectCache();
					item.Repository = Common.RepositoryDefinition.FromDisk(dialog.FileName);
					item.Repository.ID = Guid.NewGuid();
					this.AddTreeNode(item);

					using (var factory = SystemCoreInteractDomain.GetFactory(_serverName))
					{
						var server = factory.CreateChannel();
						server.SaveRepository(item.Repository, _credentials);
					}
					var n = GetRepositoryNode(item);
					n.Text = item.Repository.Name;

					RefreshFromServer();
					EnableUI();
					this.UpdateStatus();

				}
			}
			catch (Exception ex)
			{
				MessageBox.Show("An error occurred!\r\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void cmdStart_Click(object sender, EventArgs e)
		{
			if (_activeRepositoryList.Count == 0) return;

			this.UpdateStatus("Starting Repository...");
			DisableUI();
			try
			{
				foreach (var r in _activeRepositoryList)
				{
					var o = new ServiceThreader(_serverName, _credentials, r);
					o.RepositoryStarted += RepositoryStartedHandler;
					o.Error += RepositoryErrorHandler;
					var t = new System.Threading.Thread(o.StartRepository);
					t.Start();
				}
			}
			catch (Exception ex)
			{
				throw;
			}
		}

		private void cmdStop_Click(object sender, EventArgs e)
		{
			if (_activeRepositoryList.Count == 0) return;

			DisableUI();
			try
			{
				foreach (var r in _activeRepositoryList)
				{
					var o = new ServiceThreader(_serverName, _credentials, r);
					o.RepositoryStopped += new EventHandler<RepositoryEventArgs>(RepositoryStoppedHandler);
					o.Error += new EventHandler<RepositoryErrorEventArgs>(RepositoryErrorHandler);
					var t = new System.Threading.Thread(o.StopRepository);
					t.Start();
				}
			}
			catch (Exception ex)
			{
				throw;
			}
			finally
			{
				EnableUI();
			}

		}

		private void cmdExport_Click(object sender, EventArgs e)
		{
			MessageBox.Show("This functionality has not yet been implemented.", "Not Implemented", MessageBoxButtons.OK, MessageBoxIcon.Information);
			//if (this.SelecetedRepositoryNode == null) return;
			//var active = this.ActiveRepository;
			//if (active == null) return;

			//var F = new ExportDataForm(_serverName);
			//if (F.ShowDialog() == System.Windows.Forms.DialogResult.OK)
			//{
			//  this.RefreshFromServer();
			//}
		}

		public void cmdCompress_Click(object sender, EventArgs e)
		{
			if (!_isConnected) return;
			if (_activeRepositoryList.Count == 0) return;
			try
			{
				foreach (var r in _activeRepositoryList)
				{
					using (var factory = SystemCoreInteractDomain.GetFactory(_serverName))
					{
						var server = factory.CreateChannel();
						server.Compress(r.Repository.ID, _credentials);
					}
				}
			}
			catch (Exception ex)
			{
				//Do Nothing
			}
		}

		private void cmdBackup_Click(object sender, EventArgs e)
		{
			if (!_isConnected) return;
			var active = _activeRepositoryList.FirstOrDefault();
			var id = Guid.Empty;
			if (active != null) id = active.Repository.ID;
			try
			{
				var F = new BackupForm(_serverName, _credentials, id);
				F.ShowDialog();
			}
			catch (Exception ex)
			{
				//Do Nothing
			}
		}

		private void menuMainServerProp_Click(object sender, EventArgs e)
		{
			var F = new ServerInfoForm(_serverName, _credentials, _publicKey);
			F.ShowDialog();
		}

		private void cmdRestore_Click(object sender, EventArgs e)
		{
			if (!_isConnected) return;
			var active = _activeRepositoryList.FirstOrDefault();
			var id = Guid.Empty;
			if (active != null) id = active.Repository.ID;
			var F = new RestoreForm(_serverName, _credentials, id);
			if (F.ShowDialog() == System.Windows.Forms.DialogResult.OK)
			{
				this.RefreshFromServer();
			}
		}

		private void cmdExportSchema_Click(object sender, EventArgs e)
		{
			try
			{
				if (!_isConnected) return;
				if (_activeRepositoryList.Count == 0) return;
				var active = _activeRepositoryList.First();
				var dialog = new SaveFileDialog();
				dialog.Title = "Export Schema";
				dialog.FileName = active.Repository.Name + ".celeriq";
				dialog.Filter = "Schema Files (*.celeriq)|*.celeriq";
				dialog.FilterIndex = 0;
				if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
				{
					using (var factory = SystemCoreInteractDomain.GetFactory(_serverName))
					{
						var server = factory.CreateChannel();
						server.ExportSchema(active.Repository.ID, _credentials, dialog.FileName);
						MessageBox.Show("Operation complete", "Finished", MessageBoxButtons.OK, MessageBoxIcon.Information);
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show("An error occurred!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void CopyRepository()
		{
			if (!_isConnected) return;
			if (this.SelectedRepositoryNode != null)
			{
				var active = this.ActiveRepository;
				try
				{
					Clipboard.SetText(active.Repository.ToXml());
				}
				catch (Exception ex)
				{
					//Do Nothing
				}
			}
		}

		private void PasteRepository()
		{
			if (!_isConnected) return;
			var xml = string.Empty;
			try
			{
				xml = Clipboard.GetText();
			}
			catch (Exception ex)
			{
				return;
			}

			if (!string.IsNullOrEmpty(xml))
			{
				Celeriq.ManagementStudio.Objects.ConnectionCache.CreateRepository(_serverName, xml, _credentials);
				this.RefreshFromServer();
			}
		}

		private void cmdCode_Click(object sender, EventArgs e)
		{
			try
			{
				if (_activeRepositoryList.Count == 0) return;
				var active = _activeRepositoryList.First();
				if (active == null) return;

				var code = Celeriq.ManagementStudio.Objects.ClientCodeHelper.GenerateClientCode(active.Repository);
				var config = Celeriq.ManagementStudio.Objects.ClientCodeHelper.GenerateClientConfig(active.Repository, _serverName);
				var F = new CodeWindow(code, config);
				F.ShowDialog();
			}
			catch (Exception ex)
			{
				throw;
			}
		}

		private void cmdRefresh_Click(object sender, EventArgs e)
		{
			this.RefreshFromServer();
		}

		private void tvwItem_AfterSelect(object sender, TreeViewEventArgs e)
		{
			pnlContent.Controls.Clear();
			_activeRepositoryList.Clear();
			if (e.Node != null)
			{
				if (e.Node.Tag == "REPOSITORYLIST")
				{
					SelectUIRepositoryList(_currentRepositoryList);
				}
				else
				{
					var node = e.Node;
					var cache = node.Tag as RemotingObjectCache;
					if (cache == null && node.Parent != null)
						cache = node.Parent.Tag as RemotingObjectCache;

					if (cache != null)
					{
						_activeRepositoryList.Add(cache);
						SelectUIRepository(cache);
					}
				}
			}
			EnableMenus();
		}

		private void SelectUIRepository(RemotingObjectCache cache)
		{
			pnlContent.Controls.Clear();
			var ctrl = new RepositoryPropertySheet();
			ctrl.Populate(cache);
			pnlContent.Controls.Add(ctrl);
			ctrl.Dock = DockStyle.Fill;
		}

		private void SelectUIRepositoryList(List<RemotingObjectCache> list)
		{
			pnlContent.Controls.Clear();
			var ctrl = new ServerPropertySheet();
			ctrl.Populate(list);
			pnlContent.Controls.Add(ctrl);
			ctrl.Dock = DockStyle.Fill;
			ctrl.RepositoryDeleted += ctrl_RepositoryDeleted;
			ctrl.RepositorySelected += ctrl_RepositorySelected;
			ctrl.MouseUp += ctrl_MouseUp;
		}

		private void DeleteRepository(RemotingObjectCache repository)
		{
			try
			{
				using (var factory = SystemCoreInteractDomain.GetFactory(_serverName))
				{
					var server = factory.CreateChannel();

					var r = _currentRepositoryList.FirstOrDefault(x => x.Repository.ID == repository.Repository.ID);
					_currentRepositoryList.Remove(r);
					if (_activeRepositoryList.Contains(r)) _activeRepositoryList.Remove(r);

					server.DeleteRepository(repository.Repository, _credentials);
					var n = GetRepositoryNode(repository);
					if (n != null) n.Remove();
				}
			}
			catch (Exception ex)
			{
				throw;
			}
		}

		private void ShowContextMenu(Control ctrl, MouseEventArgs e)
		{
			if (_activeRepositoryList.Count > 0)
			{
				var menu = new ContextMenu();
				MenuItem newItem = null;

				newItem = new MenuItem();
				newItem.Text = "Design...";
				newItem.Click += new EventHandler(DesignMenuClick);
				newItem.Enabled = (_activeRepositoryList.Count == 1);
				menu.MenuItems.Add(newItem);

				newItem = new MenuItem();
				newItem.Text = "Design Code...";
				newItem.Click += new EventHandler(cmdCode_Click);
				newItem.Enabled = (_activeRepositoryList.Count == 1);
				menu.MenuItems.Add(newItem);

				menu.MenuItems.Add(new MenuItem() {Text = "-"});

				//newItem = new MenuItem();
				//newItem.Text = "Start";
				//newItem.Click += new EventHandler(cmdStart_Click);
				//newItem.Enabled = _activeRepositoryList.All(x => !x.IsRunning);
				//menu.MenuItems.Add(newItem);

				//newItem = new MenuItem();
				//newItem.Text = "Stop";
				//newItem.Click += new EventHandler(cmdStop_Click);
				//newItem.Enabled = _activeRepositoryList.All(x => x.IsRunning);
				//menu.MenuItems.Add(newItem);

				//menu.MenuItems.Add(new MenuItem() {Text = "-"});

				newItem = new MenuItem();
				newItem.Text = "Backup Repository...";
				newItem.Click += new EventHandler(cmdBackup_Click);
				newItem.Enabled = this.IsActiveRunning && (_activeRepositoryList.Count == 1);
				menu.MenuItems.Add(newItem);

				newItem = new MenuItem();
				newItem.Text = "Restore Repository...";
				newItem.Click += new EventHandler(cmdRestore_Click);
				newItem.Enabled = this.IsActiveRunning && (_activeRepositoryList.Count == 1);
				menu.MenuItems.Add(newItem);

				newItem = new MenuItem();
				newItem.Text = "Export Schema...";
				newItem.Click += new EventHandler(cmdExportSchema_Click);
				newItem.Enabled = (_activeRepositoryList.Count == 1);
				menu.MenuItems.Add(newItem);

				//newItem = new MenuItem();
				//newItem.Text = "Export data...";
				//newItem.Click += new EventHandler(cmdExport_Click);
				//menu.MenuItems.Add(newItem);

				newItem = new MenuItem();
				newItem.Text = "Compress";
				newItem.Click += new EventHandler(cmdCompress_Click);
				newItem.Enabled = this.IsActiveRunning;
				menu.MenuItems.Add(newItem);

				menu.Show(ctrl, e.Location);

			}
		}

		private void ctrl_MouseUp(object sender, MouseEventArgs e)
		{
			if (e.Button == System.Windows.Forms.MouseButtons.Right)
			{
				ShowContextMenu(sender as Control, e);
			}
		}

		private void ctrl_RepositorySelected(object sender, RepositoryListEventArgs e)
		{
			_activeRepositoryList.Clear();
			_activeRepositoryList.AddRange(e.RepositoryList);
		}

		private void ctrl_RepositoryDeleted(object sender, RepositoryListEventArgs e)
		{
			try
			{
				e.RepositoryList.ForEach(x => DeleteRepository(x));
			}
			catch (Exception ex)
			{
				throw;
			}
		}

		#endregion

		#region Tree Event Handlers

		private void tvwItem_MouseUp(object sender, MouseEventArgs e)
		{
			if (e.Button != System.Windows.Forms.MouseButtons.Right)
				return;

			if (this.SelectedRepositoryNode != null)
			{
				ShowContextMenu(tvwItem, e);
			}
		}

		private void DesignMenuClick(object sender, EventArgs e)
		{
			if (_activeRepositoryList.Count == 0) return;
			var active = _activeRepositoryList.First();
			ShowDesignWindow(active);
		}

		#endregion

		#region ShowDesignWindow

		private void ShowDesignWindow(RemotingObjectCache active)
		{
			if (active != null)
			{
				var F = new DesignRepositoryForm();
				F.Populate(active);
				if (F.ShowDialog() == System.Windows.Forms.DialogResult.OK)
				{
					using (var factory = SystemCoreInteractDomain.GetFactory(_serverName))
					{
						var server = factory.CreateChannel();
						active = server.SaveRepository(active.Repository, _credentials);
					}

					var n = GetRepositoryNode(active);
					n.Tag = active;
					n.Text = active.Repository.Name;
					n.ImageIndex = (active.IsRunning ? 0 : 1);
					n.SelectedImageIndex  =n.ImageIndex;
					_currentRepositoryList.Add(active);

					EnableUI();
					this.UpdateStatus();
					tvwItem.SelectedNode = n;

				}

			}
		}

		#endregion

	}
}